#include<stdio.h>
#include<iostream>
using namespace std;
#include<string.h>
#include<stdlib.h>
#include<time.h> 
typedef int Status;
#define OK true
#define ERROR false
//图：G = ( V, E )  Graph = ( Vertex, Edge )
//	V: 顶点(数据元素)的有穷非空集合
//	E: 边的有穷集合
//无向图，有向图 
//完全图：
//    无向完全图：n个顶点，n(n-1)/2条边
//	  有向完全图: n个顶点, n(n-1)条边 

//稀疏图：e < nlogn
//稠密图 
//网：边或弧带权的图
//邻接
//关联(依附)
//顶点的度：与该顶点相关联的边的数目，记作TD(v) 
//在有向图中，顶点的度 = 该顶点的入度 ID(v) + 该顶点的出度 OD(v) 
//有向树
//路径：接续的边构成的顶点序列 
//路径长度：路径上边或弧的数目/权值之和 
//回路(环): 第一个顶点和最后一个顶点相同的路径 
//简单路径：除路径起点和终点可以相同外，其余顶点均不相同的路径 
//简单回路(环): 除路径起点和终点相同外，其余顶点均不相同的路径

//连通图(强连通图), 非连通图(非强连通图)
//网：带权的图
//子图  

//连通分量(强连通分量)：无向图G的极大连通子图称为G的连通分量  
//极小连通子图 
//生成树
//生成森林    


//基本操作
//1. Create_Graph() 图的创建操作，生成一个没有顶点的空图 
//2. GetVex(G, V)  求图中的顶点的值 
//3. CreateGraph(&G, V, VR) 按照V和VR的定义构造图
//4. DFSTraverse(G) 对图进行深度优先遍历
//5. BFSTraverse(G) 对图进行广度优先遍历


//----------------图的存储结构 start------------- 
//图的逻辑结构：多对多
//图没有顺序存储结构，但可以借助二维数组来表示元素间的关系
//1.数组表示法(邻接矩阵*) 
//2.链式存储结构：多重链表(邻接表*，邻接多重表，十字链表) 



//数组(邻接矩阵)表示法：建立一个顶点表(记录各个顶点信息)和一个邻接矩阵(表示各个顶点之间的关系)
//	顶点表Vex[n]
//	图的邻接矩阵是一个二维数组A.arcs[n][n]  
// 		A.arcs[i][j] = 1 表示<i, j>∈E或者(i, j)∈E
//		A.arcs[i][j] = 0 不属于 

//  网(即有权图)的邻接矩阵表示法：
//		定义为：A.arcs[i][j] = Wij <vi, vj>或者(vi, vj) ∈VR
//				A.arcs[i][j] = ∞无边(弧) 



//邻接矩阵 
//1.邻接矩阵的存储表示：用两个数组分别存储顶点表和邻接矩阵 
#define MaxInt 32767 //表示极大值，即 ∞ 
#define MVNum 100 //最大顶点数  
typedef char VertexType;  //设顶点的数据类型为字符型 
typedef int ArcType; //自定义边的权值类型为整型 
typedef struct {
	VertexType vexs[MVNum]; //顶点表
	ArcType arcs[MVNum][MVNum]; //邻接矩阵 
	int vexnum, arcnum; //图的当前点数和边数 
}AMGraph; //Adjacency Martix Graph

//2. demo：采用邻接矩阵表示法创建无向网 (其他：无向图，有向图，有向网)
//  	(1)输入总顶点数和总边数 
//		(2)依次输入点的信息存入顶点表中
//		(3)初始化邻接矩阵，使每个权值初始化为极大值 
//		(4)构造邻接矩阵



//算法：在图中查找顶点
int LocateVex(AMGraph G, VertexType u){
	//图G中查找顶点u，存在则返回顶点表中的下标; 否则返回 -1
	for(int i = 0; i < G.vexnum; ++i){
		if(u == G.vexs[i]) return i;
	} 
	return -1;
}

//算法6.1 采用邻接矩阵表示法创建无向网 
Status CreateUDN(AMGraph &G){
	cin>>G.vexnum>>G.arcnum; //输入总顶点数，总边数  
	
	for(int i = 0; i < G.vexnum; ++i){
		cin>>G.vexs[i];  //依次输入点的信息 
	}
	
	for(int i = 0; i < G.vexnum; ++i){  //初始化邻接矩阵 
		for(int j = 0; j < G.vexnum; ++j){
			G.arcs[i][j] = MaxInt;  //边的权值均置为极大值 
		}
	}
	
	for(int k = 0; k < G.arcnum; ++k) {  //构造邻接矩阵  
		VertexType v1, v2;
		ArcType w;
		cin>>v1>>v2>>w; //输入一条边所依附的顶点及权值
		int i = LocateVex(G, v1);
		int j = LocateVex(G, v2); //确定v1, v2在G中的位置
		
		G.arcs[i][j] = w; //边<v1, v2>在G中的位置 
		G.arcs[j][i] = G.arcs[i][j]; //置<v1, v2>的对称边 <v2, v1>的权值为w 
	}
	
	return OK;
}//CreateUDN





//邻接表表示法(链式)
//		顶点：按编号顺序将顶点数据存储在一维数组中;         头结点：data , firstarc 
//		关联同一顶点的边(以顶点为尾的弧)：用线性链表存储;   表结点：临界点域adjvex , 链域nextarc, 权值 info
//无向图邻接表的特点：邻接表不唯一; 若无向图中有n个顶点，e条边，则其邻接表需要 n 个头结点 和 2e 个表结点。 适宜存储稀疏图 
//有向图的邻接表的特点：顶点vi的出度为第i个单链表的结点个数；顶点vi的入度为整个单链表中临界点域值是 i-1 的结点个数 
//有向图的逆邻接表的特点：......找入度易，找出度难 

//1.弧(边)的结点结构)如下： 
//#define MVNum 100 //最大顶点数 
#define OtherInfo int
typedef struct ArcNode{
	int adjvex; //该边所指向的顶点的位置 
	struct ArcNode *nextarc; //指向下一条边的指针
	OtherInfo info; //和边相关的信息 
}ArcNode; 

//2.顶点的结点结构如下： 
typedef struct VNode{
	VertexType data; //顶点信息
	ArcNode *firstarc; //指向第一条依附该顶点的边的指针  
}VNode, AdjList[MVNum]; //AdjList表示邻接表类型 
//AdjList v; 相当于 VNode v[MVNum]; 

//3.图的结构定义如下：
typedef struct{
	AdjList vertices; // vertices是vertex的复数 
	int vexnum, arcnum; //图的当前顶点数和弧数 
}ALGraph; 

//采用邻接表表示法创建无向网 
//算法思想：
//	(1)输入总顶点数和总边数 
//	(2)建立顶点表：依次输入点的信息输入到顶点表中，使每个表头结点的指针域初始化为NULL  
//	(3)创建邻接表
//			依次输入每条边依附的两个顶点
//			确定两个顶点的序号i和j，建立边结点
//			将此边结点分别插入vi和vj对应的两个边链表的头部 	 
int LocateVertex(ALGraph G, VertexType v){//查找顶点表中v的位置 
	for(int i = 0; i < G.vexnum; i++){
		if(G.vertices[i].data == v) return i;
	}
	return -1;
}

Status CreateALGraph(ALGraph &G, ArcNode arctex){ //采用邻接表表示法，创建无向图G  
	cin>>G.vexnum>>G.arcnum;  //输入总顶点数，总边数  
	for(int i = 0; i < G.vexnum; i++){ //输入各点，构造表头结点表 
		cout<<"请输入第"<<i+1<<"个结点的值："; 
		cin>>G.vertices[i].data; //输入顶点值  
		G.vertices[i].firstarc = NULL; //初始化表头结点的指针域 
	}
	for(int k = 0; k <G.arcnum; k++){  //输入各边，构造邻接表  
		cout<<"请输入第"<<k+1<<"条边依附的两个顶点：";
		VertexType v1, v2;  //输入一条边依附的两个顶点  
		int i = LocateVertex(G, v1);
		int j = LocateVertex(G, v2);
		
		ArcNode *p = new ArcNode; //生成一个新的边结点 *p
		p->adjvex = j; //邻接点序号为j  
		p->nextarc = G.vertices[i].firstarc;
		G.vertices[i].firstarc = p;   //头插法，将新结点*p插入顶点vi的边表头部 
		
		ArcNode *q = new ArcNode; //生成一个新的边结点 *q 
		q->adjvex = i; //邻接点序号为i  
		q->nextarc = G.vertices[j].firstarc;		
		G.vertices[j].firstarc = q; //头插法，将新结点*q插入顶点vi的边表头部 
	}
	return OK;
} //createUDG


//邻接矩阵多用于稠密图，邻接表多用于稀疏图 
//邻接表，对有向图来说，求结点的度有困难 -----> 十字链表
//邻接表，对无向图来说，每条边都要存两遍------> 邻接多重表

//存有向图的十字链表结构如下：
//顶点结点：data顶点元素, firstin第一条入弧指针, firstout第一条出弧指针 
//弧结点：tailvex弧尾位置, headvex弧头位置, hlink弧头相同的下一条弧, tlink弧尾相同的下一条弧

//存无向图的邻接多重表结构如下(p121)：
//顶点结点：data, firstedge指向第一条依附于该顶点的边
//边结点：mark标志域，标记此边是否被搜索过;  ivex该边依附的一个顶点在表头数组中的位置;  ilink指向依附于ivex的下一条边
//		  jvex该边依附的另外一个顶点在表头数组中的位置;  jlink指向依附于jvex的下一条边	 info 


 
int main(void)
{
		VertexType v1, v2;
		ArcType w;
		cin>>v1>>v2>>w;
		cout<<v1<<"\t"<<v2<<"\t"<<w;
	return 0;
}